package com.cheche.dn.infrastructure.security;

import com.google.common.base.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.stereotype.Component;

@Component("domainUsernamePasswordAuthenticationProvider")
public class DomainUsernamePasswordAuthenticationProvider implements AuthenticationProvider {

    public static final String INVALID_DOMAIN_USER_CREDENTIALS = "Invalid Domain User Credentials";

    @Autowired
    private TokenService tokenService;
    @Autowired
    @Qualifier("userServiceAuthenticator")
    private ExternalServiceAuthenticator externalServiceAuthenticator;

    @SuppressWarnings("unchecked")
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Optional<String> username = (Optional) authentication.getPrincipal();
        Optional<String> password = (Optional) authentication.getCredentials();

        if (!username.isPresent() || !password.isPresent()) {
            throw new DisabledException(INVALID_DOMAIN_USER_CREDENTIALS);
        }

        PreAuthenticatedAuthenticationToken resultOfAuthentication = externalServiceAuthenticator.authenticate(username.get(), password.get());
        String newToken = tokenService.generateNewToken(resultOfAuthentication);
        resultOfAuthentication.setDetails(newToken);
        tokenService.store(resultOfAuthentication);

        return resultOfAuthentication;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}
